package org.rcy.ruicingmarket.common.utils;

import java.text.DateFormat;
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Calendar;
import java.util.Date;
import java.util.List;

import org.apache.commons.lang3.StringUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;


/**
 * 时间工具类
 */
public class TimeUtils {

	protected static final Logger logger = LoggerFactory.getLogger(TimeUtils.class);

	public static final String DEFAULT_PATTERN = "yyyy-MM-dd";

	public static final String MONTH_PATTERN = "yyyy-MM";

	private static ThreadLocal<SimpleDateFormat> MONTH_FORMAT_LOCAL = new ThreadLocal<>();

	private static SimpleDateFormat getDateFormat() {
		SimpleDateFormat result = MONTH_FORMAT_LOCAL.get();
		if(result == null){
			result = new SimpleDateFormat(MONTH_PATTERN);
			MONTH_FORMAT_LOCAL.set(result);
		}
		return result;
	}

	public static String format(Date date) {
		return format(date, DEFAULT_PATTERN);
	}

	public static String monthFormat(Date date) {
		return getDateFormat().format(date);
	}

	public static String format(Date date, String pattern) {
		if (date == null) {
			return "";
		}
		DateFormat dateFormat = new SimpleDateFormat(pattern);
		return dateFormat.format(date);
	}

	/**
	 * 所在周的开始
	 */
	public static Date startOfWeek(Date date) {
		if (date == null) {
			return null;
		}
		Calendar c = Calendar.getInstance();
		c.setTime(date);
		c.setFirstDayOfWeek(Calendar.MONDAY);
		c.set(Calendar.DAY_OF_WEEK, Calendar.MONDAY);
		c.set(Calendar.HOUR_OF_DAY, 0);
		c.set(Calendar.MINUTE, 0);
		c.set(Calendar.SECOND, 0);
		return c.getTime();
	}

	/**
	 * 所在周的结束
	 */
	public static Date endOfWeek(Date date) {
		if (date == null) {
			return null;
		}
		Calendar c = Calendar.getInstance();
		c.setTime(date);
		c.setFirstDayOfWeek(Calendar.MONDAY);
		c.set(Calendar.DAY_OF_WEEK, Calendar.SUNDAY);
		c.set(Calendar.HOUR_OF_DAY, 23);
		c.set(Calendar.MINUTE, 59);
		c.set(Calendar.SECOND, 59);
		return c.getTime();
	}

	/**
	 * 所在月的开始
	 */
	public static Date startOfMonth(Date date) {
		if (date == null) {
			return null;
		}
		Calendar c = Calendar.getInstance();
		c.setTime(date);
		c.set(Calendar.DAY_OF_MONTH, 1);
		c.set(Calendar.HOUR_OF_DAY, 0);
		c.set(Calendar.MINUTE, 0);
		c.set(Calendar.SECOND, 0);
		c.set(Calendar.MILLISECOND, 0);
		return c.getTime();
	}

	/**
	 * 所在月的开始
	 */
	public static Date startOfMonth(String monthFormat) {
		if (StringUtils.isEmpty(monthFormat)) {
			return null;
		}
		try {
			return startOfMonth(getDateFormat().parse(monthFormat));
		} catch (ParseException e) {
			throw new RuntimeException("时间转换异常，month：" + monthFormat);
		}
	}

	/**
	 * 所在月的结束
	 */
	public static Date endOfMonth(Date date) {
		if (date == null) {
			return null;
		}
		Calendar c = Calendar.getInstance();
		c.setTime(date);
		c.set(Calendar.DAY_OF_MONTH, c.getActualMaximum(Calendar.DAY_OF_MONTH));
		c.set(Calendar.HOUR_OF_DAY, 23);
		c.set(Calendar.MINUTE, 59);
		c.set(Calendar.SECOND, 59);
		c.set(Calendar.MILLISECOND, 100);	// 设置毫秒值为100，防止数据库四舍五入
		return c.getTime();
	}

	/**
	 * 所在月的结束
	 */
	public static Date endOfMonth(String monthFormat) {
		if (StringUtils.isEmpty(monthFormat)) {
			return null;
		}
		try {
			return endOfMonth(getDateFormat().parse(monthFormat));
		} catch (ParseException e) {
			throw new RuntimeException("时间转换异常");
		}
	}

	/**
	 * 本月开始
	 */
	public static Date startOfCurMonth() {
		return startOfMonth(new Date());
	}

	/**
	 * 本月结束
	 */
	public static Date endOfCurMonth() {
		return endOfMonth(new Date());
	}

	/**
	 * 上月开始
	 */
	public static Date startOfPreMonth() {
		Calendar calendar = Calendar.getInstance();
		calendar.setTime(startOfCurMonth());
		calendar.add(Calendar.MONTH, -1);
		return calendar.getTime();
	}

	/**
	 * 上月结束
	 */
	public static Date endOfPreMonth() {
		Calendar calendar = Calendar.getInstance();
		calendar.add(Calendar.MONTH, -1);
		calendar.setTime(endOfMonth(calendar.getTime()));
		return calendar.getTime();
	}

	/**
	 * 本周开始
	 */
	public static Date startOfCurWeek() {
		return startOfWeek(new Date());
	}

	/**
	 * 本周结束
	 */
	public static Date endOfCurWeek() {
		return endOfWeek(new Date());
	}

	/**
	 * 上周开始
	 */
	public static Date startOfPreWeek() {
		Date curMon = startOfCurWeek();
		Calendar c = Calendar.getInstance();
		c.setTime(curMon);
		c.add(Calendar.DAY_OF_WEEK, -7);
		return c.getTime();
	}

	/**
	 * 上周结束
	 */
	public static Date endOfPreWeek() {
		Date curSun = endOfCurWeek();
		Calendar c = Calendar.getInstance();
		c.setTime(curSun);
		c.add(Calendar.DAY_OF_WEEK, -7);
		return c.getTime();
	}

	/**
	 * 一天的结束
	 */
	public static Date endOf(Date date) {
		if (date == null) {
			return null;
		}
		Calendar calendar = Calendar.getInstance();
		calendar.setTime(date);
		calendar.set(Calendar.HOUR_OF_DAY, 23);
		calendar.set(Calendar.MINUTE, 59);
		calendar.set(Calendar.SECOND, 59);
		calendar.set(Calendar.MILLISECOND, 100);	// 设置毫秒值为100，防止数据库四舍五入
		return calendar.getTime();
	}

	/**
	 * 一天的开始
	 */
	public static Date startOf(Date date) {
		if (date == null) {
			return null;
		}
		Calendar calendar = Calendar.getInstance();
		calendar.setTime(date);
		calendar.set(Calendar.HOUR_OF_DAY, 0);
		calendar.set(Calendar.MINUTE, 0);
		calendar.set(Calendar.SECOND, 0);
		calendar.set(Calendar.MILLISECOND,0);
		return calendar.getTime();
	}

	/**
	 * 昨天的开始
	 */
	public static Date startOfYesterday() {
		Calendar calendar = Calendar.getInstance();
		calendar.add(Calendar.DAY_OF_MONTH, -1);
		return startOf(calendar.getTime());
	}

	/**
	 * 昨天的结束
	 */
	public static Date endOfYesterday() {
		Calendar calendar = Calendar.getInstance();
		calendar.add(Calendar.DAY_OF_MONTH, -1);
		return endOf(calendar.getTime());
	}

	/**
	 * 明天的结束
	 */
	public static Date tomorrow() {
		Calendar calendar = Calendar.getInstance();
		calendar.add(Calendar.DAY_OF_MONTH, 1);
		return endOf(calendar.getTime());
	}

	/**
	 * 获取几天之后的日期
	 */
	public static Date after(Date date, int after) {
		if (date == null) {
			return null;
		}
		if (after <= 0) {
			return date;
		}
		Calendar calendar = Calendar.getInstance();
		calendar.setTime(date);
		calendar.add(Calendar.DATE, after);
		return calendar.getTime();
	}

	/**
	 * 获取几天之前的日期
	 */
	public static Date before(Date date, int before) {
		if (date == null) {
			return null;
		}
		if (before <= 0) {
			return date;
		}
		Calendar calendar = Calendar.getInstance();
		calendar.setTime(date);
		calendar.add(Calendar.DATE, -1 * before);
		return calendar.getTime();
	}

	public static Date startOfHour(Date date) {
		if (date == null) {
			return null;
		}
		Calendar calendar = Calendar.getInstance();
		calendar.setTime(date);
		calendar.set(Calendar.MINUTE, 0);
		calendar.set(Calendar.SECOND, 0);
		return calendar.getTime();
	}

	public static Date endOfHour(Date date) {
		if (date == null) {
			return null;
		}
		Calendar calendar = Calendar.getInstance();
		calendar.setTime(date);
		calendar.set(Calendar.MINUTE, 59);
		calendar.set(Calendar.SECOND, 59);
		return calendar.getTime();
	}

	/**
	 * 获取两个时间相差的月数
	 */
	public static int getMonthSpace(Date date1,Date date2)
	{
		int iMonth = 0;
		int flag = 0;
		try{
			Calendar objCalendarDate1 = Calendar.getInstance();
			objCalendarDate1.setTime(date1);

			Calendar objCalendarDate2 = Calendar.getInstance();
			objCalendarDate2.setTime(date2);

			if (objCalendarDate2.equals(objCalendarDate1)) {
				return 0;
			}
			if (objCalendarDate1.after(objCalendarDate2)){
				Calendar temp = objCalendarDate1;
				objCalendarDate1 = objCalendarDate2;
				objCalendarDate2 = temp;
			}
			if (objCalendarDate2.get(Calendar.DAY_OF_MONTH) < objCalendarDate1.get(Calendar.DAY_OF_MONTH)) {
				flag = 1;
			}

			if (objCalendarDate2.get(Calendar.YEAR) > objCalendarDate1.get(Calendar.YEAR)) {
				iMonth = ((objCalendarDate2.get(Calendar.YEAR) - objCalendarDate1.get(Calendar.YEAR))
						* 12 + objCalendarDate2.get(Calendar.MONTH) - flag)
						- objCalendarDate1.get(Calendar.MONTH);
			} else {
				iMonth = objCalendarDate2.get(Calendar.MONTH)
						- objCalendarDate1.get(Calendar.MONTH) - flag;
			}

		} catch (Exception e){
			e.printStackTrace();
		}
		return iMonth;
	}

	/**
	 * 得到日期num个月时的日期
	 * num为正数  为date后num个月
	 * num为负数  为date前num个月
	 */
	public static Date getDateOfMonth(Date date,int num){
		if(date == null){
			return null;
		}
		Calendar calendar = Calendar.getInstance(); //得到日历
		calendar.setTime(date);                     //把当前时间赋给日历
		calendar.add(Calendar.MONTH, num);          //设置为前num月
		return calendar.getTime();
	}

	/**
	 * 获得两个时间相差的天数
	 */
	public static int getDaySpace(Date minDate,Date maxDate){
		int days = (int) ((maxDate.getTime() - minDate.getTime()) / (1000*3600*24));
		return Math.abs(days);
	}

	public static List<String> dateToMonthFormat(Date startTime, Date endTime) {
		if (endTime == null) {
			endTime = new Date();
		}
		List<String> result = new ArrayList<>();
		result.add(getDateFormat().format(startTime));

		Calendar from = Calendar.getInstance();
		Calendar to = Calendar.getInstance();
		from.setTime(startTime);
		to.setTime(endTime);
		// 相差月份
		int minus = (to.get(Calendar.YEAR) - from.get(Calendar.YEAR)) * 12
				+ (to.get(Calendar.MONTH) - from.get(Calendar.MONTH));
		for (int i=0; i<minus; i++) {
			from.set(Calendar.MONTH, from.get(Calendar.MONTH) + 1);
			result.add(getDateFormat().format(from.getTime()));
		}
		return result;
	}

	public static List<String> dateToMonthFormat(String startTime, String endTime) {
		Date start = TimeUtils.startOfMonth(startTime);
		Date end = TimeUtils.endOfMonth(endTime);
		return dateToMonthFormat(start, end);
	}
	
	public static String lastMonth() {
		Calendar cal = Calendar.getInstance();
		cal.add(Calendar.MONTH, -1);
		return getDateFormat().format(cal.getTime());
	}

	public static String curMonth(Date time) {
		return getDateFormat().format(time);
	}

	public static Date curMonth(String monthFormat) {
		try {
			return getDateFormat().parse(monthFormat);
		} catch (ParseException e) {
			logger.error(e.getMessage(), e);
			return null;
		}
	}

	public static Date resetMilliSecond(Date time) {
		Calendar cal = Calendar.getInstance();
		cal.setTime(time);
		cal.set(Calendar.MILLISECOND, 0);
		return cal.getTime();
	}
	
}
